//
// Created by ftd on 2021/8/19.
//

#include "room_manager.h"
#include "utils/mutex_ext.h"
#include "demo.h"

RoomManager& RoomManager::Instance() {
    static RoomManager instance;
    return instance;
}

RoomManager::RoomManager()
        : flag_(ATOMIC_FLAG_INIT), spin_cnt_(std::thread::hardware_concurrency()){

}

RoomManager::~RoomManager() {

}


void RoomManager::OnOpenRoomOperate(OpenRoomOperate* open_oper) {
    RoomInfoPtr room_info = nullptr;
    {
        SpinLock spin_lock(flag_, spin_cnt_);
        auto it = rooms_info_.find(open_oper->room_id);
        if (it != rooms_info_.end()) {
            room_info = it->second;
        } else {
            room_info = std::make_shared<RoomInfo>();
            rooms_info_.insert({open_oper->room_id, room_info});
        }
    }

    if (room_info) {
        std::lock_guard<std::mutex> lock(room_info->mtx);
        room_info->room_status = kOpemStatus;
        room_info->room_id = open_oper->room_id;
        room_info->join_score_lower_limit = open_oper->join_score_lower_limit;
        room_info->join_level_lower_limit = open_oper->join_level_lower_limit;
        room_info->tables_cnt = open_oper->tables_cnt;
        if (!Demo::Instance().IsStressTest()) {

        }
//        fprintf(stdout,
//                "room id:%d open success, room info[join_score_lower_limit:%d join_level_lower_limit:%d tables_cnt:%d\n",
//                room_info->room_id, room_info->join_score_lower_limit, room_info->join_level_lower_limit,
//                room_info->tables_cnt);

        //do something ...
    }
}

void RoomManager::OnModifyRoomOperate(ModifyRoomOperate* modify_oper) {
    RoomInfoPtr room_info = nullptr;
    GetRoomInfo(modify_oper->room_id, &room_info);
    if (room_info) {
        std::lock_guard<std::mutex> lock(room_info->mtx);
        room_info->join_score_lower_limit = modify_oper->join_score_lower_limit;
        room_info->join_score_lower_limit = modify_oper->join_level_lower_limit;
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d modify success, join_score_lower_limit:%d join_level_lower_limit:%d\n",
                    room_info->room_id, room_info->join_score_lower_limit, room_info->join_level_lower_limit);
        }

        //do something ...
    } else {
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d is not found, modify fail\n", modify_oper->room_id);
        }
    }
}

void RoomManager::OnRestartRoomOperate(RestartRoomOperate* restart_oper) {
    RoomInfoPtr room_info = nullptr;
    GetRoomInfo(restart_oper->room_id, &room_info);
    if (room_info) {
        std::lock_guard<std::mutex> lock(room_info->mtx);
        room_info->room_status = kOpemStatus;
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d restart success\n", room_info->room_id);
        }

        //do something ...
    } else {
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d is not found, restart fail\n", restart_oper->room_id);
        }
    }
}

void RoomManager::OnDeleteRoomOperate(DeleteRoomOperate* delete_oper) {
    RoomInfoPtr room_info = nullptr;
    GetRoomInfo(delete_oper->room_id, &room_info);
    if (room_info) {
        std::lock_guard<std::mutex> lock(room_info->mtx);
        SpinLock spin_lock(flag_);
        rooms_info_.erase(delete_oper->room_id);
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d delete success\n", room_info->room_id);
        }

        //do something ...
    } else {
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d is not found, delete fail\n", delete_oper->room_id);
        }
    }
}

void RoomManager::OnCloseRoomOperate(CloseRoomOperate* close_oper) {
    RoomInfoPtr room_info = nullptr;
    GetRoomInfo(close_oper->room_id, &room_info);
    if (room_info) {
        std::lock_guard<std::mutex> lock(room_info->mtx);
        room_info->room_status = kCloseStatus;
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d close success\n", room_info->room_id);
        }
        //do something ...
    } else {
        if (!Demo::Instance().IsStressTest()) {
            fprintf(stdout, "room id:%d is not found, close fail\n", close_oper->room_id);
        }
    }
}

void RoomManager::GetRoomInfo(int room_id, RoomInfoPtr* room_info) {
    SpinLock spin_lock(flag_, spin_cnt_);
    auto it = rooms_info_.find(room_id);
    if (it != rooms_info_.end()) {
        *room_info = it->second;
    }
}
